package video

import (
	"fmt"
	"strings"
	errs "tacitus/library/error"
	"tacitus/library/format"
)

type CateNode struct {
	Category `xorm:"extends"`
	IsLink string        `json:"is_link"`
	CreateTimeStr string `json:"create_time_str" xorm:"-"`
	Children []CateNode  `json:"children" xorm:"-"`
}

func (CateNode) Columns() []string {
	return []string{"id", "parent_id", "type", "name", "remarks", "weight", "path", "create_time", "is_link"}
}

// 将要查询的字段连接成一个字符串
// t是指表别名，不用时传空字符串
// cs是指数据列列表
// em是指要替换成表达式的数据列
func JoinFields(t string, cs []string, em map[string]string) string {
	fs := make([]string, 0)
	for _, column := range cs {
		if expr, ok := em[column]; ok {
			fs = append(fs, fmt.Sprintf("%s AS `%s`", expr, column))
		} else if t != "" {
			fs = append(fs, fmt.Sprintf("`%s`.`%s`", t, column))
		} else {
			fs = append(fs, fmt.Sprintf("`%s`", column))
		}
	}
	return strings.Join(fs, ",")
}

// 显示指定父节点下的所有子节点，包括链接
func SelectCategoryNodeByParent(pid int64) (data []CateNode, err error) {
	data = make([]CateNode, 0)
	tn := rx.TableName(new(Category))
	query := "SELECT * FROM (" +
		"SELECT *, 0 AS is_link FROM `"+tn+"` WHERE parent_id = ? UNION " +
		"SELECT c.*, 1 AS is_link FROM `"+tn+"` AS c JOIN `"+rx.TableName(new(Link))+"` AS l ON l.cate_id = c.id WHERE l.parent_id = ?" +
		") AS a ORDER BY weight DESC"
	if err = rx.SQL(query, pid, pid).Find(&data); err != nil {
		return
	}
	for index, item := range data {
		data[index].ParentID = pid
		data[index].CreateTimeStr = format.DateTime(item.CreateTime)
	}
	return
}

// 显示指定节点下完整的树，只能支持一层链接否则会导致循环
func ShowCategoryNodeTree(rid int64) (tree CateNode, err error) {
	root := new(Category)
	ok, err := rx.Where("id = ?", rid).Get(root)
	if err != nil {
		return
	} else if !ok {
		err = errs.Called("指定的分类不存在")
		return
	}
	ctn := rx.TableName(new(Category))
	columns := CateNode{}.Columns()
	query := "SELECT * FROM ("+
		"SELECT "+JoinFields("", columns, map[string]string{"is_link": "0"})+" FROM "+ctn+" UNION "+
		"SELECT "+JoinFields("c", columns, map[string]string{"is_link": "1", "parent_id":"l.parent_id", "link_path": "CONCAT(p.path, l.parent_id)"})+" " +
		"FROM "+rx.TableName(new(Link))+" AS l JOIN "+ctn+" AS p ON p.id = l.parent_id JOIN t_video_cate AS c ON c.id = l.cate_id"+
		") AS a WHERE path LIKE ?"
	data := make([]CateNode, 0)
	if err = rx.SQL(query, root.Path+"%").OrderBy("create_time DESC").Find(&data); err != nil {
		return
	}
	tree, _ = HangCategoryNode(CateNode{Category:*root}, data)
	return
}

// 指定根节点数据和要挂载的数据，返回挂载好的树和剩余数据
func HangCategoryNode(root CateNode, data []CateNode) (CateNode, []CateNode) {
	root.Children = make([]CateNode, 0)
	remaining := make([]CateNode, 0)
	for _, item := range data {
		if item.ParentID == root.ID {
			var node2 CateNode
			node2, remaining = HangCategoryNode(item, data)
			root.Children = append(root.Children, node2)
		} else {
			remaining = append(remaining, item)
		}
	}
	return root, remaining
}